Editing Custom Types

The sample object has two properties, HomePhone and WorkPhone, of type PhoneNumber. The PropertyGrid control doesn’t have any built-in understanding of the PhoneNumber type, so it displays these values using their ToString() method, and allows the user to drill into them and edit their CountryCode, RegionCode and Number properties individually.

We would like to teach the PropertyGrid control a more useful way of displaying the PhoneNumber type, so that the user can see the phone number more readily and edit it more easily. To do this, we will create a type editor and attach it to the grid.

Defining the Editing Template

A type editor is basically a data template with data bindings appropriate for the edited type. The editor template for the PhoneNumber type can be pretty simple: three TextBoxes, one bound to the CountryCode property, one to the RegionCode property and one to the Number property. We will also provide some read-only TextBlocks to give the user a visual cue as to the demarcation between the boxes. So the editor data template looks like this:

CopyPhone number editor
<DataTemplate x:Key='PhoneNumberEditor'>
    <StackPanel Orientation='Horizontal'>
      <StackPanel.Resources>
        <Style TargetType='{x:Type TextBlock}'>
          <Setter Property='Foreground' Value='{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}'/>
          <Setter Property='FontWeight' Value='Bold'/>
        </Style>
        <Style TargetType='{x:Type ms:TextBox}'>
          <Setter Property='BorderThickness' Value='0'/>
        </Style>
      </StackPanel.Resources>
      <TextBlock>+</TextBlock>
      <ms:TextBox Text='{Binding Path=CountryCode, UpdateSourceTrigger=PropertyChanged}'/>
      <TextBlock> (</TextBlock>
      <ms:TextBox Text='{Binding Path=RegionCode, UpdateSourceTrigger=PropertyChanged}'/>
      <TextBlock>) </TextBlock>
      <ms:TextBox Text='{Binding Path=Number, UpdateSourceTrigger=PropertyChanged}'/>
    </StackPanel>
  </DataTemplate>

You can put templates in-line in the window or page XAML. In the sample, the template has been put in a merged ResourceDictionary to avoid cluttering up the subsequent pages.
 

Telling the Property Grid to Use the New Template

We now need to tell the PropertyGrid control to use this template for PhoneNumber objects. To do this, add a TypeEditor object to the PropertyGrid.Editors collection. You can do this using XAML property syntax as follows:

CopyTelling the property grid to use custom editors
<ms:PropertyGrid.Editors>
        <ms:TypeEditor EditedType='{x:Type t:PhoneNumber}' EditorTemplate='{StaticResource PhoneNumberEditor}'/>
      </ms:PropertyGrid.Editors>

Notice that, wherever a PhoneNumber property appears in the grid, the new editor is used to edit it.

You can also add entries to the Editors collection from code. This is useful if you don’t know at design time what types your users may have to edit – you can write code to locate editors at runtime using a configuration file or custom type attributes.
 

Combining Custom Editors With Expanding Nodes

By default, if you provide an editor for a type, the property grid will stop showing that type as expandable – users won’t be able to edit individual properties. Sometimes that’s undesirable:

To tell the PropertyGrid to allow users to expand a node even though there is an editor provided, set the AllowExpand property (or XAML attribute) of the editor to True.

See 03_EditingCustomTypes.xaml in the PropertyGridCustomization project.

Next step: Providing a Custom Editor for a Property.